Tuesday, July 20, 2004

here is the problem in more detail...

It is the same as with "super(self.__class__, self).meth()", that is, as soon as you change, or combine metaclasses for some child class, you'll get wrong method resolution, and most likely fall into infinite recursion... (see example below).

the simplest solution would be to pass the metaclass to super explicitly, but this is even worse than passing the class explicitly in the general case, as the class and the metaclass can be located in different modules/packages... etc. I can't say that this will contribute to code clarity :)

example:

 
import metaclass_example
 
 
 
class _OtherMetaClass(type):
'''
'''
def meth(cls):
print 'this is the other metaclass method!!'
# here super is in a try block so as to make the method usable
# as is (not only from class combinations).
# ....a terminated super! :))
try:
super(cls.__class__, cls).meth()
except AttributeError:
pass
 
class SomeUsefullClass(object):
'''
'''
__metaclass__ = _OtherMetaClass
 
 
# NOTE: here we inherit from two classes which are of different types
# or metaclasses, thus creating a metaclass conflict.
# to resolve this conflict we need to "combine" the metaclasses
# of the parent classes....
class _CombinationMetaclass(_OtherMetaClass, metaclass_example._MetaClass):
'''
'''
pass
 
# and here is an innocent looking result.... :)
class KillerClass(metaclass_example.SomeOtherClass, SomeUsefullClass):
'''
'''
__metaclass__ = _CombinationMetaclass
 
def meth(cls):
'''
'''
print 'hi from the killer :)'
super(cls.__class__, cls).meth()
 
 
if __name__ == '__main__':
 
SomeUsefullClass.meth()
 
killer = KillerClass()
 
print 'BANG!!!'
killer.meth()
 
 
# vim: set ts=4 sw=4 nowrap :


metaclass_example_killer.py

P.S. I made a little typo in the module name in the main post (the word example was lacking the "p" :) ), now this is corrected...

this was originaly posted here.

Sunday, July 18, 2004

ugly super class-method call...

Yesterday I stumbled on a funny problem :)

Task:
call the original class-method extended by another class-method in a subclass.

Logical Answer:
use the super function.

The Problem:
considering that the way "super" is called, is not the most beautiful feature of the Python language (this is sed to be a wart by some). this situation created a code far uglier. to be honest, I hate this solution but I can't seem to come up with a better one... does anyone have any suggestions?

the problem is that there are situations (though quite rare, or even unlikely) when this code will break!

see the example below for more details...


a full example:

 
class SomeBaseClass(object):
'''
'''
def meth(self):
'''
'''
print '###', self, self.__class__
 
 
class _MetaClass(SomeBaseClass, type):
'''
'''
def __init__(cls, name, bases, ns):
'''
'''
if 'meth' in ns:
setattr(cls, 'meth', classmethod(ns['meth']))
super(_MetaClass, cls).__init__(name, bases, ns)
 
 
class SomeClass(object):
'''
'''
__metaclass__ = _MetaClass
 
 
class SomeOtherClass(object):
'''
'''
__metaclass__ = _MetaClass
 
def meth(cls):
'''
'''
print 'this is a class-method...'
# and here is the problematic line of code:
super(cls.__class__, cls).meth() # or super(cls.__metaclass__, cls).meth()
 
 
if __name__ == '__main__':
 
basic_obj = SomeBaseClass()
some_other_obj = SomeOtherClass()
 
basic_obj.meth()
SomeClass.meth()
some_other_obj.meth()
 
# vim: set ts=4 sw=4 nowrap :


metaclass_examle.py

if anyone is interested, this is a simplified version of the structure of a module (pli.event.event or a shorthand pli.event), part of the pli library.

this was originaly posted here.

Saturday, July 17, 2004

The most promessing python projects IMHO